package bigo.data;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.AbstractSet;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * An array based implementation for Vector
 * reviewed @ Dec 4
 * @author Song Liu (sl9885@bristol.ac.uk)
 */
public class ArrayVector extends Vector {

    private float[] vector;

    public ArrayVector() {
        super(0);
    }

    /**
     * @param sizeVector The size of this vector,
     * which is also the length of this vector
     */
    public ArrayVector(int sizeVector) {
        super(0);
        vector = new float[sizeVector];
    }

    /**
     *
     * @param offset the offset of this vector, which suggests this vector
     * is splitted from other larger vector
     * @param sizeVector the size of this vector
     */
    public ArrayVector(int offset, int sizeVector) {
        super(offset);
        vector = new float[sizeVector];
    }

    public int size() {
        return vector.length;
    }

    public boolean isEmpty() {
        if (vector != null) {
            return false;
        } else {
            return true;
        }
    }

    public boolean containsKey(Object key) {
        Integer k = (Integer) key;
        if (k >= getOffset() && k < getOffset() + vector.length) {
            return true;
        } else {
            return false;
        }
    }

    public boolean containsValue(Object value) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public Float get(Object key) {
        if (!containsKey(key)) {
            return null;
        }
        return vector[(Integer) key - getOffset()];
    }

    public float[] getVector() {
        return vector;
    }

    public Float put(Integer key, Float value) {
        return vector[key - getOffset()] = value;
    }

    public Float remove(Object key) {
        float t = get(key);
        put((Integer) key, 0.0f);
        return t;
    }

    public void putAll(Map<? extends Integer, ? extends Float> m) {
        for (Integer k : m.keySet()) {
            put(k, m.get(k));
        }
    }

    public void clear() {
        Arrays.fill(vector, 0);
    }

    /**
     * Just return a fast Iterator that iterates all the indices
     * @return
     */
    public Set<Integer> keySet() {
        return new AbstractSet<Integer>() {

            @Override
            public Iterator<Integer> iterator() {
                return new Iterator<Integer>() {

                    int i = getOffset();

                    public boolean hasNext() {
                        return i < getOffset() + size();
                    }

                    public Integer next() {
                        int t = i;
                        i++;
                        return t;

                    }

                    public void remove() {
                        throw new UnsupportedOperationException("Not supported yet.");
                    }
                };

            }

            @Override
            public int size() {
                return length();
            }
        };
    }

    public Collection<Float> values() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public Set<Entry<Integer, Float>> entrySet() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public Vector duplicate() {
        ArrayVector ret = new ArrayVector();
        ret.vector = this.vector;
        ret.setOffset(getOffset());
        return ret;
    }

    @Override
    public int length() {
        return vector.length;
    }

    public void write(DataOutput out) throws IOException {
        out.writeInt(length());
        out.writeInt(getOffset());

        for (int i = 0; i < vector.length; i++) {
            out.writeFloat(vector[i]);
        }
    }

    public void readFields(DataInput in) throws IOException {
        int size = in.readInt();
        vector = new float[size];
        setOffset(in.readInt());
        
        for (int i = 0; i < size; i++) {
            vector[i] = in.readFloat();
        }
    }

    @Override
    public Vector subVector(int from, int to) {
        ArrayVector ret = new ArrayVector(from, to - from);
        System.arraycopy(vector, from, ret.vector, 0, to - from);
        return ret;
    }
}
